package com.wtwd.campus.receiver;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.annotation.MsgType;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.dao.CommandRecordMapper;
import com.wtwd.campus.dao.DeviceInfoMapper;
import com.wtwd.campus.dao.WhiteListMapper;
import com.wtwd.campus.entity.*;
import com.wtwd.campus.h5_manager.entity.DeviceLog;
import com.wtwd.campus.h5_manager.service.DeviceLogService;
import com.wtwd.campus.service.DeviceInfoService;
import com.wtwd.campus.utils.ReceiverUtils;
import com.wtwd.campus.vcom.common.Constant;
import com.wtwd.campus.vcom.dao.RequestRecordMapper;
import com.wtwd.campus.vcom.dao.VcomPhoneMapper;
import com.wtwd.campus.vcom.entity.VcomPhoneData;
import com.wtwd.campus.vcom.entity.VcomRequestRecord;
import com.wtwd.campus.vcom.service.impl.VcomDeviceInfoServiceImpl;
import com.wtwd.campus.vcom.utils.CommandSendUtils;
import com.wtwd.campus.vcom.utils.VcomPushUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 一次性设置所有白名单的设置
 *
 * @author mjy
 * @date 2021/06/30
 * @description
 */
@Service
@MsgType(value = Constants.ALL_WHITELIST_NUMBER)
public class ReceiveAllWhiteCallHandler implements IReceiverHandler {


    private static final Logger logger = LoggerFactory.getLogger(ReceiveAllWhiteCallHandler.class);

    @Autowired
    private CommandRecordMapper commandRecordMapper;
    @Autowired
    private DeviceInfoMapper deviceInfoMapper;
    @Autowired
    private WhiteListMapper whiteListMapper;
    @Autowired
    private ReceiverUtils receiverUtils;
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Autowired
    private VcomPhoneMapper vcomPhoneMapper;
    @Autowired
    private RequestRecordMapper requestRecordMapper;
    @Autowired
    private CommandSendUtils commandSendUtils;
    @Autowired
    private VcomDeviceInfoServiceImpl vcomDeviceInfoService;
    @Autowired
    private VcomPushUtils vcomPushUtils;
    @Autowired
    private DeviceLogService deviceLogService;

    @Value("${h5.customerId.ryh5}")
    private Integer ryh5CustomerId;

    @Override
    public void handlerMessage(MqMessage mqMessage) {
        MqAllWhiteCallResult mqAllWhiteCallResult = (MqAllWhiteCallResult) mqMessage.getObject();
        String imei = mqAllWhiteCallResult.getImei();
        String commandNumber = mqAllWhiteCallResult.getCommandNumber();
        DeviceInfo deviceInfo = deviceInfoMapper.getDeviceInfoByImei(mqAllWhiteCallResult.getImei());
        //处理指令回复的时间
        String deviceDate = mqAllWhiteCallResult.getDeviceDate();
        String deviceTime = mqAllWhiteCallResult.getDeviceTime();
        Long time = getTime(deviceDate, deviceTime);
        if (deviceInfo != null) {
            MqLocationData mqLocationData = mqAllWhiteCallResult.getMqLocationData();
            if (mqLocationData != null) {
                if (mqLocationData.getLatitude() != 0 && mqLocationData.getLongitude() != 0) {
                    //进行定位数据存储以及围栏告警记录的存储
                    deviceInfo = receiverUtils.dealLocation(mqAllWhiteCallResult.getMqLocationData(), time, deviceInfo, 1);
                }
            }
            //修改设备信息
            deviceInfo.setLastUpTime(time);
            deviceInfoService.modifyDeviceInfo(deviceInfo);
            // 平台设备与客户设备做不同处理，H5没调用批量设置
            if (deviceInfo.getDeviceType() == 1) {
                platformWhiteCall(mqAllWhiteCallResult.getWhiteList(), deviceInfo, commandNumber, time);
            } else if (deviceInfo.getDeviceType() == 2) {
                customerWhiteCallDeal(mqAllWhiteCallResult.getWhiteList(), deviceInfo, commandNumber, time);
            } else if (deviceInfo.getDeviceType() == 5) {
                // 威科姆白名单/亲情号处理
                dealVcomDevice(deviceInfo, mqAllWhiteCallResult.getWhiteList(), commandNumber, time);
            } else if (deviceInfo.getDeviceType() == 3) {//福建睿翼e15增加批量指令处理
                if (deviceInfo.getCustomerId() == ryh5CustomerId) {//按平台处理
                    platformWhiteCall(mqAllWhiteCallResult.getWhiteList(), deviceInfo, commandNumber, time);
                }
            }
            //删除缓存中的指令
            String delKey = Constants.ALL_WHITELIST_NUMBER.concat("-").concat(commandNumber);
            receiverUtils.deleteCommandInRedis(imei, delKey);
            //存储设备接收日志
            DeviceLog deviceLog = new DeviceLog();
            deviceLog.setSendUser(Constants.DEVICE_USER);
            deviceLog.setImei(imei);
            deviceLog.setBigType(Constants.MESS_TYPE);
            deviceLog.setType(Constants.ALL_WHITELIST_NUMBER);
            JSONObject contant = new JSONObject();
            contant.put("设备号", imei);
            contant.put("序列号", mqAllWhiteCallResult.getSequenceList());
            contant.put("日期", mqAllWhiteCallResult.getDeviceDate());
            contant.put("经度", mqLocationData.getLongitude());
            contant.put("纬度", mqLocationData.getLatitude());
            contant.put("设备回复白名单数据集合", mqAllWhiteCallResult.getWhiteList());
            contant.put("时间", mqAllWhiteCallResult.getDeviceTime());
            deviceLog.setCmd(contant.toJSONString());
            deviceLog.setSendTime(System.currentTimeMillis());
            deviceLog.setCommandNumber(commandNumber);
            deviceLog.setState(1);
            deviceLogService.addDeviceLog(deviceLog);
        } else {
            saveUnInStorage(imei);
            receiverUtils.cloaseChannel(imei);
        }
    }

    /**
     * 平台白名单处理
     *
     * @param upWhiteList
     * @param deviceInfo
     */
    private void platformWhiteCall(List<Map<String, String>> upWhiteList, DeviceInfo deviceInfo, String commandNumber, Long time) {
        //比对修改前后数据完善白名单数据库表
        List<DeviceWhiteList> whiteList = new ArrayList<>();
        List<Integer> delSequence = new ArrayList<>();
        //添加设备上传的白名单列表
        for (Map<String, String> map : upWhiteList) {
            Integer wlNum = Integer.parseInt(map.get("wlNum"));
            String wlPhone = map.get("wlPhone");
            if (StringUtils.isBlank(wlPhone)) {
                delSequence.add(wlNum);
                continue;
            }
            DeviceWhiteList deviceWhiteList = new DeviceWhiteList();
            deviceWhiteList.setStatus(1);
            Integer isAffection = -1;
            if (wlNum > 6) {
                isAffection = 0;
            } else if (wlNum >= 3 && wlNum <= 6) {
                isAffection = 1;
            }
            deviceWhiteList.setIsAffection(isAffection);
            deviceWhiteList.setWhiteName(map.get("wlName"));
            deviceWhiteList.setWhitePhone(wlPhone);
            deviceWhiteList.setSequence(Integer.parseInt(map.get("wlNum")));
            deviceWhiteList.setDeviceId(deviceInfo.getDeviceId());
            whiteList.add(deviceWhiteList);
        }
        //删除数据库中需要删除的白名单
        if (delSequence != null && delSequence.size() != 0) {
            whiteListMapper.delDeviceWhiteList(deviceInfo.getDeviceId(), delSequence);
        }
        //执行修改白名单
        if (whiteList != null && whiteList.size() > 0) {
            whiteListMapper.modifyWhiteList(whiteList);
        }
        //将指令状态改为完成
        receiverUtils.completeCommandRecord(Constants.ALL_WHITELIST_NUMBER, deviceInfo.getImei(), commandNumber, null, Constants.COMMAND_COMPLETE, time);
    }

    /**
     * 客户白名单处理
     *
     * @param upWhiteList
     * @param deviceInfo
     */
    private void customerWhiteCallDeal(List<Map<String, String>> upWhiteList, DeviceInfo deviceInfo, String commandNumber, Long time) {
        Iterator<Map<String, String>> iterator = upWhiteList.iterator();
        List<DeviceWhiteList> whiteList = new ArrayList<>();
        // 删除类型（因为亲情号和白名单都有可能调用这个方法，需要清除原来的数据。因此根据序列号去区分
        int delType = 2;
        while (iterator.hasNext()) {
            Map<String, String> map = iterator.next();
            Integer seq = Integer.parseInt(map.get("wlNum"));
            String phone = map.get("wlPhone");
            if (seq > 6) {
                delType = 1;
            }
            if (StringUtils.isNotBlank(phone)) {
                DeviceWhiteList deviceWhiteList = new DeviceWhiteList();
                deviceWhiteList.setStatus(1);
                deviceWhiteList.setIsAffection(Integer.parseInt(map.get("wlType")) == 1 ? 1 : 0);
                deviceWhiteList.setWhiteName(map.get("wlName"));
                deviceWhiteList.setWhitePhone(phone);
                deviceWhiteList.setSequence(Integer.parseInt(map.get("wlNum")));
                deviceWhiteList.setDeviceId(deviceInfo.getDeviceId());
                whiteList.add(deviceWhiteList);
            }
        }
        // 全部删除
        whiteListMapper.delDeviceAllWhiteListByDeviceId(deviceInfo.getDeviceId(), delType);
        // 批量添加
        whiteListMapper.addSomeWhiteList(whiteList);
        //将指令状态改为完成
        receiverUtils.completeCommandRecord(Constants.ALL_WHITELIST_NUMBER, deviceInfo.getImei(), commandNumber, null, Constants.COMMAND_COMPLETE, time);
    }

    /**
     * 处理Vcom的设备
     */
    public void dealVcomDevice(DeviceInfo deviceInfo, List<Map<String, String>> whiteList, String commandNumber, Long time) {
        String imei = deviceInfo.getImei();
        if (deviceInfo.getDeviceType() == Constant.VCOM_DEVICE_TYPE) {
            if (whiteList != null) {
                //处理回复数据并补全个数
                List<Map<String, String>> convertList = new ArrayList<>();
                List<Integer> seqList = new ArrayList<>();
                for (Map<String, String> e : whiteList) {
                    String sequence = e.get("wlNum");
                    String name = e.get("wlName");
                    String phone = e.get("wlPhone");
                    Map<String, String> addMap = new HashMap<>();
                    addMap.put("name", name);
                    addMap.put("phone", phone);
                    addMap.put("sequence", sequence);
                    convertList.add(addMap);
                    seqList.add(Integer.valueOf(sequence));
                }
                int type = getPhoneType(seqList);
                if (type == Constant.PHONE_FAMILY) {
                    convertList = completeList(seqList, convertList, 3, 4, 6);
                } else if (type == Constant.PHONE_WHITE) {
                    convertList = completeList(seqList, convertList, 17, 7, 23);
                }
                //完善号码记录表
                VcomPhoneData phoneRecord = new VcomPhoneData();
                //修改内容、完成状态、修改时间
                phoneRecord.setPhoneData(JSONObject.toJSONString(convertList));
                phoneRecord.setStatus(Constant.PHONE_STATUS_NORMAL);
                phoneRecord.setUpdateTime(time);
                phoneRecord.setCommandNumber(commandNumber);
                phoneRecord.setImei(imei);
                phoneRecord.setType(type);
                logger.info("数据库执行vcom更新号码数据 imei={},type={}",imei,type);
                vcomPhoneMapper.updateVcomPhoneDateByImeiAndType(phoneRecord);
                //完善请求表
                VcomRequestRecord requestRecord = requestRecordMapper.getRequestRecord(imei, commandNumber, type);
                if (requestRecord == null) {
                    return;
                }
                requestRecord.setCompleteTime(time);
                requestRecord.setStatus(Constant.STATUS_COMPLETE);
                requestRecordMapper.modifyRequestRecord(requestRecord);
                logger.info("vcom指令记录完成 requestId={}",requestRecord.getRequestId());
                //选择一条指令进行下发
                VcomRequestRecord oldestSending = requestRecordMapper.getOldestSendingCommand(imei, type);
                if (oldestSending == null) {
                    VcomRequestRecord oldestNotSend = requestRecordMapper.getOldestNotSendCommand(imei, type);
                    if (oldestNotSend != null && !requestRecord.getRequestId().equals(oldestNotSend.getRequestId())) {
                        logger.info("vcom缓存指令自动下发",oldestNotSend.getId());
                        requestRecordMapper.updateCommandSendStatus(oldestNotSend.getId(), Constant.STATUS_SEND);
                        //进行指令下发
                        if (type == Constant.PHONE_WHITE) {
                            JSONArray array = JSONObject.parseArray(oldestNotSend.getRequestContent());
                            vcomDeviceInfoService.useDealWhiteNo(array, oldestNotSend);
                        } else if (type == Constant.PHONE_FAMILY) {
                            JSONArray array = JSONObject.parseArray(oldestNotSend.getRequestContent());
                            vcomDeviceInfoService.useDealFamilyNo(array, oldestNotSend);
                        }
                    }
                }
                // 推送给Vcom
                vcomPushUtils.commandComplete(imei, commandNumber, type, Constant.PHONE_STATUS_NORMAL);
            }
        }
    }

    /**
     * 补全亲情号码和白名单号码
     *
     * @param seqList
     * @param list
     * @param size
     * @param start
     * @param end
     * @return
     */
    public List<Map<String, String>> completeList(List<Integer> seqList, List<Map<String, String>> list, int size, int start, int end) {
        //亲情号码不足则补全
        if (list.size() < size) {
            for (int i = start; i <= end; i++) {
                if (!seqList.contains(i)) {
                    Map<String, String> map = new HashMap<>();
                    map.put("name", "");
                    map.put("phone", "");
                    map.put("sequence", String.valueOf(i));
                    list.add(map);
                }
            }
        }
        return list;
    }

    /***
     *
     *根据键位判断号码类型(此处因为是根据类型发送号码数据的,情亲号，白名单，故其实传过来的键位只可能是一种类型)
     * 只需分辨情亲号白名单
     * @param seqList
     * @return
     */
    private int getPhoneType(List<Integer> seqList) {
        if (seqList == null || seqList.size() == 0) {
            return 0;
        } else {//直接取第一位判断号码类型，则判断整个号码类型组
            Integer seq = seqList.get(0);
            if (4 <= seq && seq <= 6) {//情亲号
                return 2;
            } else {
                return 3;
            }
        }
    }

}


